/***************************************************************************
 * File name: EPubPointer.h
 * Original author: caizhifei2003@163.com
 * Date: 2013.03.01
 ***************************************************************************/
#ifndef _EPUB_POINTER_H_
#define _EPUB_POINTER_H_

#include "EPubBase.h"

template<class T>
class EPubPointer
{
public:
	EPubPointer() : m_Ptr(NULL) { }
	EPubPointer(T *ptr) : m_Ptr(ptr) { if(m_Ptr) { m_Ptr->AddRef(); } }
	EPubPointer(const EPubPointer &other) : m_Ptr(other.m_Ptr) { if(m_Ptr) { m_Ptr->AddRef(); } }
	~EPubPointer() { if(m_Ptr) { m_Ptr->Release(); } }

	T *Get() { return m_Ptr; }
	const T *Get() const { return m_Ptr; }
	T *operator *() { return m_Ptr; }
	const T *operator *() const { return m_Ptr; }
	T *operator->() { return m_Ptr; }
	const T *operator->() const { return m_Ptr; }
	operator bool() const { return m_Ptr != NULL; }

	bool operator ==(const EPubPointer<T> &other) const { return (*m_Ptr) == other; }
	bool operator !=(const EPubPointer<T> &other) const { return !((*this) == other); }

	bool operator >(const EPubPointer<T> &other) const { return (*this) > (*other.m_Ptr); }
	bool operator <(const EPubPointer<T> &other) const { return (*this) < (*other.m_Ptr); }

	EPubPointer<T> &operator =(T *ptr)
	{
		if(ptr) { ptr->AddRef(); }
		if(m_Ptr) { m_Ptr->Release(); }
		m_Ptr = ptr;
		return *this;
	}

	const EPubPointer<T> &operator =(const T *ptr)
	{
		T *ptr = const_cast<T *>(ptr);
		return operator=(ptr);
	}

	EPubPointer<T> &operator =(EPubPointer<T> &other)
	{
		return operator=(other.m_Ptr);
	}

	/*const EPubPointer<T> &operator =(const EPubPointer<T> &other)
	{
		return operator=(other.m_Ptr);
	}*/

	template<class TParent>
	EPubPointer<TParent> Cast()
	{
		return static_cast<TParent *>(m_Ptr);
	}

	template<class TParent>
	const EPubPointer<TParent> Cast() const
	{
		return static_cast<TParent *>(m_Ptr);
	}

	template<class TChild>
	EPubPointer<TChild> As()
	{
		return dynamic_cast<TChild *>(m_Ptr);
	}

	template<class TChild>
	const EPubPointer<TChild> As() const
	{
		return dynamic_cast<TChild *>(m_Ptr);
	}

private:
	T *			m_Ptr;
};

#endif // _EPUB_POINTER_H_